package com.tuni.birthdaymoney.service.util.email;

import java.util.Calendar;

import org.joda.time.DateTime;

/**
 * Stores some static routines (for Calendar operating?)
 * 
 * @author Nikita Krenev
 * 
 */
public class BirthdayUtils {

    /**
     * Sets time to 00:00:00
     * 
     * @param c
     *            Calendar to modify
     */
    public static void makeMidnight(Calendar c) {
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
    }

    /**
     * Converts birthday to nearest actual birthday (in the current or next
     * year):
     * <ul>
     * <li>makes year current, if birthday will be celebrated today or in the
     * rest of current year
     * <li>makes year current+1, if birthday will be celebrated in the next year
     * </ul>
     * Examples:
     * <ul>
     * <li>getNextBirthday(20/11/1980, 02/05/2013) = 20/11/2013
     * <li>getNextBirthday(02/05/1996, 02/05/2013) = 02/05/2013
     * <li>getNextBirthday(16/02/1974, 02/05/2013) = 16/02/2014
     * </ul>
     * 
     * @param birthday
     *            Birthday
     * @param today
     *            Current date
     * @return Next actual birthday. The time is forced to 00:00:00.
     */
    public static Calendar getNextBirthday(Calendar birthday, Calendar today) {
        Calendar result = (Calendar) birthday.clone();

        makeMidnight(result);
        makeMidnight(today);
        result.set(Calendar.YEAR, today.get(Calendar.YEAR));

        if (!equalDayMonth(today, result) && result.before(today)) {
            result.add(Calendar.YEAR, 1);
        }

        return result;
    }

    /**
     * Checks if two dates are equal, <b>without matter of time & year</b>
     * 
     * @param c1
     *            Some calendar
     * @param c2
     *            Another calendar
     * @return true/false
     */
    public static boolean equalDayMonth(Calendar c1, Calendar c2) {
        return (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH)) && (c1.get(Calendar.DAY_OF_MONTH) == c2.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * Checks if two dates are equal, <b>without matter of time</b>
     * 
     * @param c1
     *            Some calendar
     * @param c2
     *            Another calendar
     * @return true/false
     */
    public static boolean equalDayMonthYear(Calendar c1, Calendar c2) {
        return (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)) && (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH))
                && (c1.get(Calendar.DAY_OF_MONTH) == c2.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * Checks if birthday is in (currentDate, currentDate + periodDays] without
     * matter of year
     * 
     * @param birthday
     * @param currentDate
     * @param periodDays
     * @return True or false, it depends.
     */
    public static boolean isBirthdaySoon(DateTime birthday, Calendar currentDate, int periodDays) {

        // for better boundary conditions handling
        currentDate.set(Calendar.HOUR_OF_DAY, 12);
        birthday = birthday.withYear(currentDate.get(Calendar.YEAR)).withHourOfDay(0);
        DateTime from = new DateTime(currentDate);
        DateTime to = new DateTime(currentDate).plusDays(periodDays);

        return birthday.isAfter(from) && birthday.isBefore(to);
    }
}